import Global
from entity.Entrust import *
from entity.Futures import Futures
from entity.Holding import *
from entity.Stock import Stock


class User:
    money = 0.0
    lockMoney = 0.0
    allMoney = 0.0
    holdingStockList = []
    holdingFuturesList = []
    entrustBuyList = []
    entrustSellList = []

    def __init__(self, money=10000):
        self.money = money
        self.allMoney = money
        Global.userList.append(self)

    def addEntrust(self, stockOrFutures, num, price, entrustType, case=1, pry=1):
        if type(stockOrFutures) == Stock:
            stock = stockOrFutures
            if entrustType == "buy":
                self.entrustBuyList.append(EntrustStock(stock, num, price))
                self.lockMoney += price * num  # 设置冻结资产
                self.money -= price * num  # 设置用户金额
                self.reloadAllMoney()  # 设置用户总资产
            if entrustType == "sell":
                self.entrustSellList.append(EntrustStock(stock, num, price))
                for holding in self.holdingStockList:  # 冻结股票
                    holding.lockNum += num  # 添加冻结股票数量
                    holding.num -= num  # 设置可操作股票数量

        if type(stockOrFutures) == Futures:
            futures = stockOrFutures
            if entrustType == "buy":
                self.entrustBuyList.append(EntrustFutures(futures, num, price, case, pry))
                self.lockMoney += price * num  # 设置冻结资产
                self.money -= price * num  # 设置用户金额
                self.reloadAllMoney()  # 设置用户总资产
            if entrustType == "sell":
                self.entrustSellList.append(EntrustFutures(futures, num, price, case, pry))
                for holding in self.holdingFuturesList:  # 冻结股票
                    if holding.num < num:  # 如果删除的数量超过当前仓的数量
                        if holding.num > 0:  # 并且有可操作
                            holding.lockNum += holding.num
                            holding.num = 0
                            num -= holding.num
                        continue
                    holding.lockNum += num  # 添加冻结股票数量
                    holding.num -= num  # 设置可操作股票数量
                    return

    def delEntrust(self, stockOrFutures, num, price, entrustType, case=1, pry=1):
        if type(stockOrFutures) == Stock:
            stock = stockOrFutures
            if entrustType == "buy":
                for entrust in self.entrustBuyList:
                    if entrust.stock == stock and entrust.num == num and entrust.price == price:
                        self.entrustBuyList.remove(entrust)
                        return "删除出售委托成功"
            if entrustType == "sell":
                for entrust in self.entrustSellList:
                    if entrust.stock == stock and entrust.num == num and entrust.price == price:
                        self.entrustSellList.remove(entrust)
                        return "删除购买委托成功"
        if type(stockOrFutures) == Futures:
            futures = stockOrFutures
            if entrustType == "buy":
                for entrust in self.entrustBuyList:
                    if entrust.futures == futures and entrust.num == num and entrust.price == price \
                            and entrust.case == case and entrust.pry == pry:
                        self.entrustBuyList.remove(entrust)
                        return "删除出售委托成功"
            if entrustType == "sell":
                for entrust in self.entrustSellList:
                    if entrust.futures == futures and entrust.num == num and entrust.price == price \
                            and entrust.case == case and entrust.pry == pry:
                        self.entrustSellList.remove(entrust)
                        return "删除购买委托成功"
        return "找不到该委托"

    def _addHolding(self, stockOrFutures, num, buyPrice, case=1, pry=1):
        if type(stockOrFutures) == Stock:
            stock = stockOrFutures
            for holding in self.holdingStockList:
                if holding.stock == stock:
                    holding.addNum(num, stock.nowPrice)
                    return
            self.holdingStockList.append(HoldingStock(stock, num, buyPrice))
        if type(stockOrFutures) == Futures:
            futures = stockOrFutures
            self.holdingFuturesList.append(HoldingFutures(futures, num, buyPrice, case, pry))

    def _delHolding(self, stockOrFutures, num, case=1, pry=1, isEntrust=False):
        if type(stockOrFutures) == Stock:
            stock = stockOrFutures
            for holding in self.holdingStockList:
                if holding.stock == stock:
                    if isEntrust:
                        holding.lockNum -= num

                        return
                    holding.num -= num
                    if holding.num + holding.lockNum == 0:
                        self.holdingStockList.remove(holding)
                    return
        if type(stockOrFutures) == Futures:
            futures = stockOrFutures
            for holding in self.holdingFuturesList:
                if holding.futures == futures and holding.case == case and holding.pry == pry:
                    if isEntrust:
                        holding.lockNum -= num
                        num = num - holding.lockNum
                    else:
                        holding.num -= num
                        num = num - holding.lockNum
                    if holding.lockNum + holding.num <= 0:
                        self.holdingFuturesList.remove(holding)
                    if num < 0:  # 当前的卖完了 继续往下卖
                        self.holdingFuturesList.remove(holding)
                        self._delHolding(stockOrFutures, -num, case=case, isEntrust=isEntrust)
                    return

    def reloadAllMoney(self):
        self.allMoney = 0  # 重置总资产
        for stock in Global.stockList:  # 遍历所有股票
            for holding in self.holdingStockList:  # 获取所有持股
                if holding.stock == stock:  # 获取持股代码 与 股票代码 相同
                    self.allMoney += (holding.num + holding.lockNum) * stock.nowPrice  # 计算该持股的价值
        self.allMoney += self.money + self.lockMoney  # 将冻结资产加上
        for holding in self.holdingFuturesList:
            holding.reload()
            self.allMoney += holding.value

    def startEntrust(self):

        for entrustBuy in self.entrustBuyList:
            if type(entrustBuy) == EntrustStock:
                if entrustBuy.price >= entrustBuy.stock.nowPrice:  # 委托生效
                    self.lockMoney -= (entrustBuy.num * entrustBuy.price)  # 移除冻结资金
                    self._addHolding(entrustBuy.stock, entrustBuy.num, entrustBuy.price)
                    if Global.openEntrustInfo:
                        print("委托已购入 股票" + str(entrustBuy.stock.code) +
                              " 数量:" + str(entrustBuy.num) +
                              " 价格:" + str(entrustBuy.price))
                    self.entrustBuyList.remove(entrustBuy)  # 删除委托

            if type(entrustBuy) == EntrustFutures:
                if entrustBuy.price >= entrustBuy.futures.nowPrice and entrustBuy.case == 1:  # 委托生效
                    self.lockMoney -= (entrustBuy.num * entrustBuy.price)  # 移除冻结资金
                    self._addHolding(entrustBuy.futures, entrustBuy.num, entrustBuy.price)
                    if Global.openEntrustInfo:
                        print("委托已买多 期货" + str(entrustBuy.futures.code) + " 数量:" + str(
                            entrustBuy.num) + " 价格:" + str(
                            entrustBuy.price))
                if entrustBuy.price <= entrustBuy.futures.nowPrice and entrustBuy.case == -1:  # 委托生效
                    self.lockMoney -= (entrustBuy.num * entrustBuy.price)  # 移除冻结资金
                    self._addHolding(entrustBuy.futures, entrustBuy.num, entrustBuy.price)
                    if Global.openEntrustInfo:
                        print("委托已卖空 期货" + str(entrustBuy.futures.code) + " 数量:" + str(
                            entrustBuy.num) + " 价格:" + str(
                            entrustBuy.price))

                self.entrustBuyList.remove(entrustBuy)  # 删除委托

        for entrustSell in self.entrustSellList:

            if type(entrustSell) == EntrustStock:
                if entrustSell.price <= entrustSell.stock.nowPrice:  # 委托生效
                    self.money += entrustSell.price * entrustSell.num  # 设置用户金额
                    self._delHolding(entrustSell.stock, entrustSell.num, isEntrust=True)  # 设置用户持股
                    self.reloadAllMoney()  # 设置用户总资产

                    if Global.openEntrustInfo:
                        print("委托已出售 股票" +
                              str(entrustSell.stock.code) +
                              " 数量:" + str(entrustSell.num) +
                              " 价格:" + str(entrustSell.price))
                    self.entrustSellList.remove(entrustSell)  # 删除委托

            if type(entrustSell) == EntrustFutures:
                if entrustSell.price <= entrustSell.futures.nowPrice:  # 委托生效
                    self.money += entrustSell.price * entrustSell.num  # 设置用户金额
                    self._delHolding(entrustSell.futures, entrustSell.num, case=entrustSell.case, isEntrust=True)
                    if Global.openEntrustInfo:
                        print("委托已出售 期货" + str(entrustSell.futures.code) +
                              " 数量:" + str(entrustSell.num) +
                              " 价格:" + str(entrustSell.price))
                    self.entrustSellList.remove(entrustSell)  # 删除委托

        self.reloadAllMoney()  # 设置用户总资产

    def put(self):
        self.reloadAllMoney()

        print("钱包:", '%.3f' % self.money,
              " 冻结:", '%.3f' % self.lockMoney,
              " 总资产:", '%.3f' % self.allMoney)

        print("持股:")
        for var in self.holdingStockList:
            var.reload()
            if len(self.entrustBuyList) == 0 and len(self.entrustSellList) == 0:
                print(" 股号:", var.stock.code,
                      " 数量:", var.num,
                      " 买入单价:", var.buyPrice,
                      " 买入总价", '%.3f' % var.buyAllPrice,
                      " 盈利:", '%.3f' % var.profit,
                      " 利润率:", '%.3f' % var.profitRatio)
            else:
                print(" 股号:", var.stock.code,
                      " 数量:", var.num,
                      " 冻结:", var.lockNum,
                      " 买入单价:", var.buyPrice,
                      " 买入总价", '%.3f' % var.buyAllPrice,
                      " 盈利:", '%.3f' % var.profit,
                      " 利润率:", '%.3f' % var.profitRatio)
        print("期货:")
        for var in self.holdingFuturesList:

            var.reload()
            if var.case == -1:
                print(" 【卖空】 代号:", var.futures.code,
                      " 可用数量:", var.num,
                      " 冻结数量:", var.lockNum,
                      " 买入价格", '%.3f' % var.buyAllPrice,
                      " 目前价值:", '%.3f' % var.value,
                      " 利润:", '%.3f' % var.profit,
                      " 利润率", '%.3f' % var.profitRatio,
                      " 杠杆:", var.pry)
            if var.case == 1:
                print(" 【买多】 代号:", var.futures.code,
                      " 可用数量:", var.num,
                      " 冻结数量:", var.lockNum,
                      " 买入价格", '%.3f' % var.buyAllPrice,
                      " 目前价值:", '%.3f' % var.value,
                      " 利润:", '%.3f' % var.profit,
                      " 利润率", '%.3f' % var.profitRatio,
                      " 杠杆:", var.pry)

        print("委托:")
        for var in self.entrustBuyList:
            if type(var) == EntrustStock:
                print("购买  股号:", var.stock.code,
                      "  数量:", var.num,
                      "  价格:", var.price)
            if type(var) == EntrustFutures:
                if var.case == 1:
                    print("买多  股号:", var.futures.code,
                          "  数量:", var.num,
                          "  单价:", var.price)
                if var.case == -1:
                    print("卖空  股号:", var.futures.code,
                          "  数量:", var.num,
                          "  单价:", var.price)
        for var in self.entrustSellList:
            if type(var) == EntrustStock:
                print("出售  股号:", var.stock.code,
                      "  数量:", var.num,
                      "  价格:", var.price)
            if type(var) == EntrustFutures:
                if var.case == 1:
                    print("平仓买多  股号:", var.futures.code,
                          "  数量:", var.num,
                          "  单价:", var.price)
                if var.case == -1:
                    print("平仓卖空  股号:", var.futures.code,
                          "  数量:", var.num,
                          "  单价:", var.price)

    def getHoldingStock(self, stock):
        for holding in self.holdingStockList:
            if holding.code == stock.code:
                return holding
        return None

    def buy(self, stockOrFutures, num, price, case=1, pry=1, autoEntrust=False):

        if type(stockOrFutures) == Stock:
            stock = stockOrFutures
            if self.money < price * num:
                return "金额不足"
            if price >= stock.nowPrice:  # 判断是否购买成功
                self.money -= price * num  # 设置用户金额
                self._addHolding(stock, num, price)  # 设置用户持股
                self.reloadAllMoney()  # 设置用户总资产
                return '成功购入 股票:' + str(stock.code) + ' 数量:' + str(num) + ' 价格:' + str(price)
            elif autoEntrust:
                self.addEntrust(stock, num, price, "buy")  # 添加购买委托
                return "已添加购买委托"
            else:
                return "购入失败"

        if type(stockOrFutures) == Futures:
            futures = stockOrFutures

            if price == 0:
                return "请输入买入单价"
            if self.money < price * num:
                return "金额不足"

            if price < futures.nowPrice and case == 1:
                if autoEntrust:
                    self.addEntrust(futures, num, price, "buy", case=case, pry=pry)  # 添加购买委托
                    return "已添加建仓委托"
                return "买入失败"
            if price > futures.nowPrice and case == -1:
                if autoEntrust:
                    self.addEntrust(futures, num, price, "buy", case=case, pry=pry)  # 添加购买委托
                    return "已添加建仓委托"
                return "建仓失败"

            self._addHolding(futures, num, price, case=case, pry=pry)
            self.money -= price * num
            self.reloadAllMoney()  # 设置用户总资产
            if case == 1:
                return '买多 代号:' + str(futures.code) + "  单价:" + str(price) + "  杠杆:" + str(pry)
            if case == -1:
                return '卖空 代号:' + str(futures.code) + "  单价:" + str(price) + "  杠杆:" + str(pry)

    def sell(self, stockOrFutures, num, price, case=1, pry=1, autoEntrust=False):
        if type(stockOrFutures) == Stock:
            stock = stockOrFutures
            for holding in self.holdingStockList:
                if holding.stock == stock and holding.num < num:
                    return "你没有那么多持股"
            if price <= stock.nowPrice:
                self.money += price * num  # 设置用户金额
                self._delHolding(stock, num)  # 设置用户持股
                self.reloadAllMoney()  # 设置用户总资产
                return "已出售 股票" + str(stock.code) + " 数量:" + str(num) + " 价格:" + str(price)
            elif autoEntrust:
                self.addEntrust(stock, num, price, "sell")
                return "已添加出售委托"
            else:
                return "出售失败"
        if type(stockOrFutures) == Futures:
            futures = stockOrFutures
            holdingAllNum = 0
            for holding in self.holdingFuturesList:
                if holding.futures == futures and holding.case == case and holding.pry == pry:
                    holdingAllNum += holding.num
            if holdingAllNum < num:
                return "你没有持有那么多"

            if price > futures.nowPrice and case == 1:
                if autoEntrust:
                    self.addEntrust(futures, num, price, "sell", case=case, pry=pry)
                    return "已添加出售委托"
                return "卖出失败"
            if price < futures.nowPrice and case == -1:
                if autoEntrust:
                    self.addEntrust(futures, num, price, "sell", case=case, pry=pry)
                    return "已添加出售委托"
                return "卖出失败"

            self.money += price * num  # 设置用户金额
            self._delHolding(futures, num, case=case, pry=pry)  # 删除用户持股
            self.reloadAllMoney()  # 设置用户总资产

            if case == 1:
                return "已平仓 买多 期货" + str(futures.code) + " 数量:" + str(num) + " 单价:" + str(price)
            if case == -1:
                return "已平仓 卖空 期货" + str(futures.code) + " 数量:" + str(num) + " 单价:" + str(price)
